<?php
if(!class_exists('XConfig', false)){
	require(XFRAMEWORK_DIR.'/core/config/XConfig.php');
}
if(!class_exists('XBasicAnnotationParser', false)){
	require(dirname(__FILE__).DIRECTORY_SEPARATOR.'XBasicAnnotationParser.php');
}
if(!class_exists('XFactory', false)){
	require(XFRAMEWORK_DIR.'/core/context/factory/XFactory.php');
}
/** 
 * XAnnotation
 * 
 * #en Annotation Holder Class
 * #zh 含有类注解信息的类
 * 
 * @final
 */
final class XAnnotation{
	private static $singletons = array();
	private static $extensions = array();
	private $reflection = null;
	private $annotations = null;
	private $methodAnnotations = null;
	private $propertyAnnotations = null;

	private function __construct($class) {
		$this->reflection = new ReflectionClass($class);
	}
	
	/** 
	 * @return XAnnotation
	 */
	public static function singleton($class) {
		if (!isset(self::$singletons[$class])) {
			self::$singletons[$class] = new XAnnotation($class);
		}
		if(!self::$extensions){
			self::$extensions = XConfig::singleton()->get('project.annotation.extensions');
			if(!self::$extensions){
				self::$extensions = array();
			}
		}
		return self::$singletons[$class];
	}

	/** 
	 * @return ReflectionClass
	 */	
	public function reflection(){
		return $this->reflection;
	}
	
	/** 
	 * @return mixed
	 */
	public function get($key){
		$annotations = $this->annotations();
		return x_array_get($annotations, $key);
	}
	
	/** 
	 * @return array
	 */	
	public function annotations(){
		if(is_null($this->annotations)){			
			$comment = $this->reflection()->getDocComment();
			$this->annotations = $this->_parse($comment);
		}
		return $this->annotations;
	}
	
	/** 
	 * @return array
	 */		
	public function methodAnnotations(){
		if(is_null($this->methodAnnotations)){					
			$this->methodAnnotations = array();	
			$methods = $this->reflection()->getMethods();
			foreach($methods as $method){
				$comment = $method->getDocComment();
				if(!$comment){
					continue;
				}
				x_array_set($this->methodAnnotations, $method->getName(), $this->_parse($comment));
			}
		}
		return $this->methodAnnotations;
	}	
	
	/** 
	 * @return mixed
	 */		
	public function method($key){
		$methodAnnotations = $this->methodAnnotations();
		return x_array_get($methodAnnotations, $key);
	}
	
	/** 
	 * @return array
	 */		
	public function propertyAnnotations(){
		if(is_null($this->propertyAnnotations)){
			$this->propertyAnnotations = array();	
			$properties = $this->reflection()->getProperties();
			foreach($properties as $property){
				$comment = $property->getDocComment();
				if(!$comment){
					continue;
				}
				x_array_set($this->propertyAnnotations, $property->getName(), $this->_parse($comment));
			}
		}
		return $this->propertyAnnotations;
	}
	
	/** 
	 * @return mixed
	 */		
	public function property($key){
		$propertyAnnotations = $this->propertyAnnotations();
		return x_array_get($propertyAnnotations, $key);
	}	
	
	private function _parse($comment){
		if(is_array(self::$extensions) && count(self::$extensions) > 0){
			foreach(self::$extensions as $key => $value){
				if(!preg_match("/{$key}/i", $this->reflection()->getName())){
					continue;
				}		
				if(!XClassLoader::loader($value)->implementsInterface('XAnnotationsParser')){
					continue;
				}
				$parser = XFactory::singleton()->get($value, 'singleton');
				$annotations = $parser->parse($comment);	
				if(is_array($annotations) && count($annotations) > 0){
					return $annotations;
				}
			}
		}
		$parser = XFactory::singleton()->get('XBasicAnnotationParser', 'singleton');
		return $parser->parse($comment);		
	}
}
?>